﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Weapp.ControlLibrary.CustomBasicControlers;

namespace Weapp.ControlLibrary
{
    public enum InterceptMouseWheelMode
    {
        /// <summary>MouseWheel always works (defauld behavior)</summary>
        Always,
        /// <summary>MouseWheel works only when mouse is over the (focused) control</summary>
        WhenMouseOver,
        /// <summary>MouseWheel never works</summary>
        Never
    }
    public partial class NumericUpDownField : BaseField
    {
        #region Constructors
        public NumericUpDownField()
        {
            InitializeComponent();
            EnabledTextFieldBackColor = Color.White;
            numericUpDownEx1.BackColor = enabledTextFieldBackColor;
            ButtonsWidth = 15;
            SizeComponents();
            AlignComponents();
        }
        #endregion

        #region Private Members
        private System.Drawing.Color onFocusControlColor;
        private HorizontalAlignment textAlign;
        private int buttonsWidth;
        private InterceptMouseWheelMode _interceptMouseWheel = InterceptMouseWheelMode.Always;
        private bool _wrapValue = false;
        private Color enabledTextFieldBackColor;
        #endregion

        #region Properties
        [Description("The field value (displayed on top of the line)."), Category("Appearance")]
        public decimal FieldValue
        {
            get { return numericUpDownEx1.Value; }
            set { numericUpDownEx1.Value = value; }
        }
        [DefaultValue(15)]
        [Description("+/- buttons width."), Category("Appearance")]
        public int ButtonsWidth
        {
            get { return buttonsWidth; }
            set
            {
                // bool indicating whether the new value is indeed 
                // different from the old one
                bool raiseEvent = buttonsWidth != value;
                // assign the value to the backing field
                buttonsWidth = value;
                // raise the event if the value has changed
                if (raiseEvent)
                {
                    NumericUpDownField_ButtonsWidthChanged(this, EventArgs.Empty);
                }
            }
        }
        [DefaultValue(typeof(CustomNumericUpDown.InterceptMouseWheelMode), "Always")]
        [Category("Behavior")]
        [Description("Enables MouseWheel only under certain conditions.")]
        public CustomNumericUpDown.InterceptMouseWheelMode InterceptMouseWheel
        {
            get { return numericUpDownEx1.InterceptMouseWheel; }
            set { numericUpDownEx1.InterceptMouseWheel = value; }
        }
        /// <summary>
        /// If set, incrementing value will cause it to restart from Minimum 
        /// when Maximum is reached (and viceversa).
        /// </summary>
        [Category("Behavior")]
        [DefaultValue(false)]
        [Description("If set, incrementing value will cause it to restart from Minimum when Maximum is reached (and viceversa).")]
        public bool WrapValue
        {
            get { return numericUpDownEx1.WrapValue; }
            set { numericUpDownEx1.WrapValue = value; }
        }
        [Category("Behavior")]
        [DefaultValue(true)]
        [Description("Enables MouseWheel only under certain conditions.")]
        public bool InterceptArrowKeys { get; set; }
        [Description("The background color of the control's textbox when it's enabled."), Category("Appearance")]
        public Color EnabledTextFieldBackColor
        {
            get { return enabledTextFieldBackColor; }
            set { enabledTextFieldBackColor = value; }
        }
        #endregion

        #region HiddenProperties
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new BorderStyle BorderStyle { get; set; }

        [DefaultValue("")]
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Image BackgroundImage { get; set; }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override ImageLayout BackgroundImageLayout { get; set; }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode { get; set; }
        #endregion

        #region Events
        protected override void BaseField_TextAlignChanged(EventArgs e)
        {
            AlignComponents();
            base.BaseField_TextAlignChanged(e);
        }
        protected override void BaseField_SizeChanged(object sender, EventArgs e)
        {
            if (numericUpDownEx1 != null)
            {
                SizeComponents();
                AlignComponents();
            }
            base.BaseField_SizeChanged(sender, e);
        }
        protected override void BaseField_BackColorChanged(object sender, EventArgs e)
        {
            numericUpDownEx1.BackColor = BackColor;
            base.BaseField_BackColorChanged(sender, e);
        }
        protected override void BaseField_ForeColorChanged(object sender, EventArgs e)
        {
            numericUpDownEx1.ForeColor = ForeColor;
            base.BaseField_ForeColorChanged(sender, e);
        }
        protected override void BaseField_EnabledChanged(object sender, EventArgs e)
        {
            numericUpDownEx1.Enabled = Enabled;
            if (Enabled)
            {
                numericUpDownEx1.BackColor = EnabledTextFieldBackColor;
            }
            else
            {
                numericUpDownEx1.BackColor = BackColor;
            }
            base.BaseField_EnabledChanged(sender, e);
        }
        private void NumericUpDownField_FontChanged(object sender, EventArgs e)
        {
            if (numericUpDownEx1 != null)
            {
                numericUpDownEx1.Font = new Font(Font.FontFamily, Font.Size, Font.Style);
                Size = new Size(Width, numericUpDownEx1.Height + LabelFieldName.Height + 1);
                SizeComponents();
            }
        }
        private void NumericUpDownField_ButtonsWidthChanged(object sender, EventArgs e)
        {
            SizeComponents();
            AlignComponents();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            numericUpDownEx1.DownButton();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            numericUpDownEx1.UpButton();
        }
        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            button1.ForeColor = OnFocusControlColor;
        }
        private void button1_MouseUp(object sender, MouseEventArgs e)
        {
            button1.ForeColor = ForeColor;
        }
        private void button2_MouseDown(object sender, MouseEventArgs e)
        {
            button2.ForeColor = OnFocusControlColor;
        }
        private void button2_MouseUp(object sender, MouseEventArgs e)
        {
            button2.ForeColor = ForeColor;
        }
        #endregion

        #region Methods
        private void AlignComponents()
        {
            numericUpDownEx1.TextAlign = TextAlign;
            switch (TextAlign)
            {
                case HorizontalAlignment.Center:
                    button1.Left = 0;
                    button2.Left = Width - ButtonsWidth;
                    numericUpDownEx1.Left = 0;
                    break;
                case HorizontalAlignment.Left:
                    button1.Left = Width - ButtonsWidth - ButtonsWidth;
                    button2.Left = Width - ButtonsWidth;
                    numericUpDownEx1.Left = 0;
                    break;
                case HorizontalAlignment.Right:
                    button1.Left = 0;
                    button2.Left = ButtonsWidth;
                    numericUpDownEx1.Left = 0;
                    break;
                default:
                    button1.Left = Width - ButtonsWidth - ButtonsWidth;
                    button2.Left = Width - ButtonsWidth;
                    numericUpDownEx1.Left = 0;
                    break;
            }
            button1.BringToFront();
            button2.BringToFront();
        }
        private void SizeComponents()
        {
            numericUpDownEx1.Width = Width;
            Height = numericUpDownEx1.Height + LabelFieldName.Height + 1;
            button1.Height = numericUpDownEx1.Height;
            button2.Height = numericUpDownEx1.Height;
            button1.Width = ButtonsWidth;
            button2.Width = ButtonsWidth;
            button1.BringToFront();
            button2.BringToFront();
        }
        #endregion
    }
}